import json

# Create your views here.
from datetime import datetime

from django.db.models import Sum
from django.http import JsonResponse
from rest_framework.views import APIView

from apps.bookkeeping.bookserialization import DisburseIncomeSerialization, IncomeDisburseTypeSerialization, \
    PlanSerialization
from apps.bookkeeping.utils.image_storage import storage
from common.response_code import RET, error_map
from db.models import XlzDisburse, XlzUserIncomeDisburse, XlzIncomeDisburseType, XlzIncome, XlzPlan


class Bookkeeping(APIView):
    """
    记账模块:支出,收入模块记录
    """
    serializer = DisburseIncomeSerialization

    def post(self, request):
        """
        添加用户支出和收入记录
        :param request:
        :return:
        """
        # 获取参数
        dict_keepaccounts = {}
        keepaccounts_type = request.data.get("keepaccounts_type", "")
        user_id = request.user.id
        type_id = request.data.get("type_id", None)
        money = request.data.get("money", -1.0)
        try:
            money = float(money)
        except:
            return JsonResponse(
                {"msg": error_map[RET.DATAERR], "code": RET.DATAERR})
        description = request.data.get("description", "")
        keepaccounts_time = request.data.get("keepaccounts_time", "")
        if keepaccounts_time:
            try:
                keepaccounts_time = datetime.strptime(keepaccounts_time, '%Y-%m-%d')
                dict_keepaccounts["keepaccounts_time"] = keepaccounts_time
                if keepaccounts_time.year < request.user.create_time.year:
                    raise Exception

            except Exception:
                return JsonResponse(
                    {"msg": error_map[RET.TIME_FORMAT_ERROR], "code": RET.TIME_FORMAT_ERROR})
        if description:
            dict_keepaccounts["description"] = description
        dict_keepaccounts.update(
            dict(keepaccounts_type=keepaccounts_type, user_id=user_id, type_id=type_id, money=money))

        disburse = self.serializer(data=dict_keepaccounts)
        if disburse.is_valid():
            dis = disburse.save()
            dis.save()

            # 判断是否存在正在执行的计划
            plan = XlzPlan.objects.filter(user_id=user_id, is_activate=2).first()
            if plan:
                if isinstance(dis, XlzDisburse):
                    plan.money -= dis.money
                else:
                    plan.money += dis.money
                plan.save()


        else:
            return JsonResponse(
                {"msg": error_map[RET.PARAMERR], "code": RET.PARAMERR})
        return JsonResponse({"code": "200", "msg": "添加成功"})

    def get(self, request):
        user_id = request.user.id
        "参数,需要一个时间,年份的时间"
        date = request.query_params.get("date", "")

        if date:
            try:
                date = datetime.strptime(date, '%Y')
                if date.year > datetime.now().year or date.year < request.user.create_time.year:
                    raise Exception
            except Exception:
                return JsonResponse(
                    {"msg": error_map[RET.TIME_FORMAT_ERROR], "code": RET.TIME_FORMAT_ERROR})
        else:
            date = datetime.now()

        disburses = XlzDisburse.objects.filter(user_id=user_id, keepaccounts_time__year=date.year)
        incomes = XlzIncome.objects.filter(user_id=user_id, keepaccounts_time__year=date.year)
        data_list = []
        disburse_money_all = float(0)
        income_money_all = float(0)
        months = datetime.now().month + 1 if datetime.now().year == date.year else 13
        for month in range(1, months):
            data_dict = {"month": month}

            disburse_months = disburses.filter(keepaccounts_time__month=month)
            income_months = incomes.filter(keepaccounts_time__month=month)

            # 获取支出数据
            disburse_money = disburse_months.aggregate(Sum("money")).get(
                "money__sum") if disburse_months.exists() else float(0)
            income_money = income_months.aggregate(Sum("money")).get(
                "money__sum") if income_months.exists() else float(0)

            data_dict.update(
                {"disburse": float(disburse_money), "income": float(income_money),
                 "surplus_money": income_money - disburse_money})
            disburse_money_all += disburse_money
            income_money_all += income_money

            data_list.append(data_dict)

        data_json = {
            "code": RET.OK,
            "msg": error_map[RET.OK],
            "user_create": request.user.create_time.year,
            "data": {
                "surplus": float(income_money_all - disburse_money_all),
                "disburse_money_all": float(disburse_money_all),
                "income_money_all": float(income_money_all),
                "detail": data_list,
            }
        }

        return JsonResponse(data_json)


class BookkeepingType(APIView):
    """获取用户设置的支出和支出类型和设置类型"""
    serializer = IncomeDisburseTypeSerialization

    def get(self, request):
        setting = request.query_params.get("setting", None)

        ## 获取到用户的支出和收入类型
        user_id = request.user.id
        user_type = XlzUserIncomeDisburse.objects.filter(user_id=user_id).first()
        # 获取所有的支出类型
        disburse_type = eval(user_type.disburse_type)
        disburses = XlzIncomeDisburseType.objects.filter(id__in=disburse_type)
        disburses = self.serializer(instance=disburses, many=True)
        # 获取所有的收入类型数据
        income_type = eval(user_type.income_type)
        incomes = XlzIncomeDisburseType.objects.filter(id__in=income_type)
        incomes = self.serializer(instance=incomes, many=True)

        resp = {"code": RET.OK,
                "msg": error_map[RET.OK],
                'data': {
                    "disburses": disburses.data,
                    "incomes": incomes.data
                }
                }

        if setting == "setting":
            # 获取用户没有设置的支出类型
            no_incomes = XlzIncomeDisburseType.objects.exclude(id__in=disburse_type)
            no_incomes = self.serializer(instance=no_incomes, many=True)
            # 获取用户没有设置的收入类型
            no_disburses = XlzIncomeDisburseType.objects.exclude(id__in=income_type)
            no_disburses = self.serializer(instance=no_disburses, many=True)
            resp['no_data'] = {
                "no_disburses": no_incomes.data,
                "no_incomes": no_disburses.data,
            }

        return JsonResponse(resp)

    def put(self, request):
        user_id = request.user.id
        # 类型 ,支出收入类型id,添加或者删除
        kookkeepingtype = request.data.get("kookkeepingtype")
        type_id = request.data.get("type_id")

        activity = request.data.get("activity")

        if not kookkeepingtype in ["disburse", "income"]:
            return JsonResponse({"code": RET.PARAMERR, "msg": error_map[RET.PARAMERR]})

        try:
            type_id = int(type_id)
            XlzIncomeDisburseType.objects.get(pk=type_id)
        except Exception:
            return JsonResponse({"code": RET.TYPE_ID_ERROR, "msg": error_map[RET.TYPE_ID_ERROR]})

        if not activity in ["add", "del"]:
            return JsonResponse({"code": RET.PARAMERR, "msg": error_map[RET.PARAMERR]})

        user_type = XlzUserIncomeDisburse.objects.filter(user_id=user_id).first()

        if kookkeepingtype == "disburse":
            types = user_type.disburse_type
        else:
            types = user_type.income_type

        types = eval(types)  # 变成 set集合
        if activity == "add":
            if type_id in types:
                return JsonResponse({"code": RET.ADD_ERROR, "msg": error_map[RET.ADD_ERROR]})

            types.add(type_id)
        else:
            if not type_id in types:
                return JsonResponse({"code": RET.DEL_ERROR, "msg": error_map[RET.DEL_ERROR]})
            types.discard(type_id)

        if kookkeepingtype == "disburse":
            user_type.disburse_type = str(types)
        else:
            user_type.income_type = str(types)
        user_type.save()
        return JsonResponse({"code": RET.OK, "msg": error_map[RET.OK]})

    def delete(self, request):
        # 删除数据
        # kookkeepingtype:记账类型
        # type_id : 删错记录的类型id
        user_id = request.user.id
        kookkeepingtype = request.data.get("kookkeepingtype")
        if not kookkeepingtype in ["disburse", "income"]:
            return JsonResponse({"code": RET.PARAMERR, "msg": error_map[RET.PARAMERR]})
        type_id = request.data.get("type_id")
        try:
            type_id = int(type_id)
            XlzIncomeDisburseType.objects.get(pk=type_id)
        except Exception:
            return JsonResponse({"code": RET.TYPE_ID_ERROR, "msg": error_map[RET.TYPE_ID_ERROR]})

        if kookkeepingtype == "disburse":
            querysets = XlzDisburse.objects.filter(user_id=user_id, type_id=type_id)

        else:
            querysets = XlzIncome.objects.filter(user_id=user_id, type_id=type_id)

        if not querysets.exists():
            return JsonResponse({"code": RET.NODATA, "msg": error_map[RET.NODATA]})

        querysets.delete()
        return JsonResponse({"code": RET.OK, "msg": error_map[RET.OK]})


# 存钱计划相关接口


class PlanView(APIView):
    serializer = PlanSerialization

    def get(self, request):
        """返回存钱计划"""
        user_id = request.user.id
        # 当前计划
        current_plan = XlzPlan.objects.filter(user_id=user_id, is_activate=2).first()

        if not current_plan:
            return JsonResponse({"code": RET.NODATA, "msg": error_map[RET.NODATA]})
        # 序列化

        current_plan = self.serializer(instance=current_plan)
        # 其他计划
        plans = XlzPlan.objects.filter(user_id=user_id, is_activate__in=[0, 1]).order_by("-create_time").all()
        if plans.exists():
            plans = self.serializer(instance=plans, many=True)
            plans = plans.data
        else:
            plans = None
        plan_dict = {
            "code": RET.OK,
            "msg": error_map[RET.OK],
            'data': {
                "current_plan": current_plan.data,
                "plans": plans
            }
        }
        return JsonResponse(plan_dict)

    def post(self, request):
        """添加存钱计划"""
        user_id = request.user.id

        img_data = request.FILES.get("image", None)
        if img_data is None or not img_data.name.split(".")[-1].lower() in ["jpg", 'png', 'jpeg']:
            return JsonResponse({"code": RET.IMAGE_ERROR, "msg": error_map[RET.IMAGE_ERROR]})

        target = request.data.get("target")
        try:
            target = float(target)
        except Exception:
            return JsonResponse({"code": RET.PARAMERR, "msg": error_map[RET.PARAMERR]})
        if target <= 0:
            return JsonResponse({"code": RET.PARAMERR, "msg": error_map[RET.PARAMERR]})

        # 判断是否存在正在执行的计划
        plan = XlzPlan.objects.filter(user_id=user_id, is_activate=2).first()
        if plan:
            if plan.money >= plan.target:
                plan.is_activate = 0
            else:
                plan.is_activate = 1
            plan.save()

        # 上传图片
        try:
            img_url = storage(img_data.read())
        except Exception:
            return JsonResponse({"code": RET.THIRDERR, "msg": error_map[RET.THIRDERR]})
        new_plan = XlzPlan(user_id=user_id, is_activate=2, target=target, img_url=img_url)
        new_plan.save()

        return JsonResponse({"code": RET.OK, "msg": error_map[RET.OK]})


class UserMonthVIew(APIView):

    def get(self, request):
        user_id = request.user.id
        date = datetime.now()
        disburses = XlzDisburse.objects.filter(user_id=user_id, keepaccounts_time__year=date.year,
                                               keepaccounts_time__month=date.month)
        incomes = XlzIncome.objects.filter(user_id=user_id, keepaccounts_time__year=date.year,
                                           keepaccounts_time__month=date.month)
        # 获取支出数据
        disburse_money = disburses.aggregate(Sum("money")).get(
            "money__sum") if disburses.exists() else float(0)
        income_money = incomes.aggregate(Sum("money")).get(
            "money__sum") if incomes.exists() else float(0)

        return JsonResponse({
            "code": RET.OK,
            "msg": error_map[RET.OK],
            "data": {
                "month": date.month,
                "surplus": income_money - disburse_money,
                "income_money": income_money,
                "disburse_money": disburse_money,
            }
        }
        )
